package com.linklee.Chapter3;

import java.lang.reflect.Array;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Chapter3Homework {

    public static void mian(String[]agrs){






    }

    //Question1-a
    public int addUp(Stream<Integer> numbers){
       return  numbers.reduce(0,(initNumber,element)->initNumber+element);
    }
    public int addUp(List<Integer> numbers){
        return addUp(numbers.stream());
    }

    //Question1-b
    public List<String> getNamesAndOrigins(List<Map<String,String>> artists){
        return artists.stream()
                .flatMap(map->Stream.of(map.get("name"),map.get("origins")))
                .collect(Collectors.toList());
    }

    //Question1-c
    public List<List<Map<String,String>>> getList(List<List<Map<String,String>>> lists){
        return lists.stream()
                .filter(list->list.size()<=3)
                .collect(Collectors.toList());
    }

    //Question2
    public int getMemberNumbers(){
        List<List<Map>> lists = new ArrayList<>();

        return lists.stream()
                .map(list->list.size())
                .reduce(0,(initNumber,element)->initNumber+element);
    }

    //Question6

    public static int getLowwerCharsNumber(String a){
       return  (int)a.chars().filter(chars->Character.isLowerCase(chars)).count();
    }

    //Question7

    public Optional<String> getha(List<String> strings){
        return strings.stream()
                .max(Comparator.comparing(Chapter3Homework::getLowwerCharsNumber));
    }

    //Exercises Question 2

    public static <I, O> List<O> map(Stream<I> stream, Function<I, O> mapper) {
        return stream.reduce(new ArrayList<O>(), (acc, x) -> {
            // We are copying data from acc to new list instance. It is very inefficient,
            // but contract of Stream.reduce method requires that accumulator function does
            // not mutate its arguments.
            // Stream.collect method could be used to implement more efficient mutable reduction,
            // but this exercise asks to use reduce method.
            List<O> newAcc = new ArrayList<>(acc);
            newAcc.add(mapper.apply(x));
            return newAcc;
        }, (List<O> left, List<O> right) -> {
            // We are copying left to new list to avoid mutating it.
            List<O> newLeft = new ArrayList<>(left);
            newLeft.addAll(right);
            return newLeft;
        });
    }

}
